/*
 * jlib.cc
 *
 *  Created on: Dec 3, 2010
 *      Author: fify
 */

#include "jlib.h"
#include "jconfig.h"
#include "jrouter.h"
#include "properties.h"
#include <stdio.h>
#include <string>
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
using std::string;

namespace CncrJConfig
{

class JConfigArgs
{
public:
	char *username, *passwd, *host, *cmds;
	int port, timeout;

	int ret;	// Return value of the thread.

	JConfigArgs(char *username, char *passwd, char *host, int port, char *cmds, int timeout)
	{
		this->username = new char[strlen(username) + 1];
		this->passwd = new char[strlen(passwd) + 1];
		this->host = new char[strlen(host) + 1];
		this->port = port;
		this->cmds = new char[strlen(cmds) + 1];
		this->timeout = timeout;

		strcpy(this->username, username);
		strcpy(this->passwd, passwd);
		strcpy(this->host, host);
		strcpy(this->cmds, cmds);

		this->ret = -1;
	}
	virtual ~JConfigArgs()
	{
		if(username != NULL)
			delete username;
		if(passwd != NULL)
			delete passwd;
		if(host != NULL)
			delete host;
		if(cmds != NULL)
			delete cmds;
	}
};

int jconfig(char *username, char *passwd, char* host, int port, char *cmds)
{
	JConfig * p_jconfig = new JConfig();
	CncrVDevice::VJRouter *p_jrouter = new CncrVDevice::VJRouter();

#ifdef DEBUG
	printf("Connecting: Username = %s, passwd = %s, host = %s, port = %d\n", username, passwd, host, port);
#endif
	sleep(3);
	for(;;)
	{
		if(p_jconfig->init(host, port) < 0)
		{
			printf("\033[32m" "Connecting failed, trying again..\n" "\033[0m");
			sleep(3);
			continue;
		}
		else
			break;
	}

	for(;;)
	{
		printf("\033[31m" "Wait the olive to start.\n" "\033[0m");
		if(!p_jconfig->junos_started())
		{
			sleep(1);
		}
		else
			break;
	}

	printf("Ready to login.\n");

	if(p_jconfig->enter_status(string(username), string(passwd), STATUS_CONFIG) < 0)
	{
		p_jconfig->perror("enter status error");
		return -1;
	}

	string cmds_str(cmds);
	p_jrouter->add_cmds(cmds_str);

	string code;
	string result;
	while(p_jrouter->cmd_count() > 0)
	{
		p_jrouter->generate_code(0, code);
		//cout << code << endl;
		if(p_jconfig->configure(code) < 0)
		{
			p_jconfig->perror("Configure error");
			return -1;
		}

		p_jrouter->remove_cmd(0);
	}

	int ret = p_jconfig->check_and_commit();

	delete p_jconfig;
	delete p_jrouter;

	return ret;
}

void* jconfig_thread(void *data)
{
	JConfigArgs * args = (JConfigArgs *) data;

	while(1)
	{
		args->ret = jconfig(args->username, args->passwd, args->host, args->port, args->cmds);
		if(args->ret >= 0)
		{
			break;
		}
	}

	return NULL;
}

int jconfig(char *username, char *passwd, char *host, int port, char *cmds, int timeout)
{
	JConfigArgs *args = new JConfigArgs(username, passwd, host, port, cmds, timeout);

	args->ret = -1;

	pthread_t tid;
	pthread_create(&tid, NULL, &jconfig_thread, (void *)args);
	pthread_join(tid, NULL);

	while(timeout--)
	{
		if(args->ret >= 0)
			return args->ret;
		sleep(1);
	}

	printf("Timeout event occurs, exiting..\n");
	pthread_cancel(tid);

	return -1;
}

}// End of namespace.
